#include<iostream>
#include<list>

using namespace std;

// 完美转发
void Fun(int& x) { cout << "左值引用" << endl; }

void Fun(const int& x) { cout << "const 左值引用" << endl; }

void Fun(int&& x) { cout << "右值引用" << endl; }

void Fun(const int&& x) { cout << "const 右值引用" << endl; }

// 模板中的&&不代表右值引用，而是万能引用，其既能接收左值又能接收右值。
// 模板的万能引用只是提供了能够接收同时接收左值引用和右值引用的能力，
// 但是引用类型的唯一作用就是限制了接收的类型，后续使用中都退化成了左值，
// 我们希望能够在传递过程中保持它的左值或者右值的属性, 就需要用我们下面学习的完美转发
//template<typename T>
//void PerfectForward(T&& t)// T&& -> 传什么T&&就替换成什么
//{
//	Fun(t);
//}

template<typename T>
void PerfectForward(T&& t)
{
	Fun(forward<T>(t));
}

// 完美转发---实则是类模板
//void PerfectForward(int& t)
//{
//	Fun(t);
//}
//
//void PerfectForward(int&& t)
//{
//	Fun(move(t));
//}
//
//void PerfectForward(const int& t)
//{
//	Fun(t);
//}
//
//void PerfectForward(const int&& t)
//{
//	Fun(move(t));
//}

//int main()
//{
//	PerfectForward(10);// 右值
//
//	int a;
//	PerfectForward(a); // 左值
//
//	PerfectForward(std::move(a)); // 右值
//
//	const int b = 8;
//	PerfectForward(b);// const 左值
//
//	PerfectForward(std::move(b)); // const 右值
//
//	return 0;
//}

// 完美转发使用场景
//template<class T>
//struct ListNode
//{
//	ListNode* _next = nullptr;
//	ListNode* _prev = nullptr;
//	T _data;
//};
//
//template<class T>
//class List
//{
//	typedef ListNode<T> Node;
//public:
//	List()
//	{
//		_head = new Node;
//		_head->_next = _head;
//		_head->_prev = _head;
//	}
//
//	void PushBack(T&& x)
//	{
//		//Insert(_head, x);
//		Insert(_head, std::forward<T>(x));
//	}
//
//	void PushFront(T&& x)
//	{
//		//Insert(_head->_next, x);
//		Insert(_head->_next, std::forward<T>(x));
//	}
//
//	void Insert(Node* pos, T&& x)
//	{
//		Node* prev = pos->_prev;
//		Node* newnode = new Node;
//		newnode->_data = std::forward<T>(x); // 关键位置
//		// prev newnode pos
//		prev->_next = newnode;
//		newnode->_prev = prev;
//		newnode->_next = pos;
//		pos->_prev = newnode;
//	}
//
//	void Insert(Node* pos, const T& x)
//	{
//		Node* prev = pos->_prev;
//		Node* newnode = new Node;
//		newnode->_data = x; // 关键位置
//		// prev newnode pos
//		prev->_next = newnode;
//		newnode->_prev = prev;
//		newnode->_next = pos;
//		pos->_prev = newnode;
//	}
//
//private:
//	Node* _head;
//};
//
//int main()
//{
//	List<string> lt;
//	lt.PushBack("1111");
//	lt.PushFront("2222");
//	return 0;
//}


// 新的类功能
// 默认成员函数 --- 移动构造函数 和 移动赋值运算符重载
// 移动构造函数：没有自己实现移动构造函数，且没有实现析构函数 、拷贝构造、拷贝赋值重载中的任 意一个
// 如果你提供了移动构造或者移动赋值，编译器不会自动提供拷贝构造和拷贝赋值


// 可变参数模板
//template <class ...Args>
//void ShowList(Args ...args)
//{}

//可变模板参数
//参数类型可变
//参数个数可变
//template<class ...Args>
//void ShowList(Args... args)
//{
//	//可变参数模板编译时解析
//	cout << sizeof...(args) << endl;
//	//下面运行获取和解析，所以不支持这样用
//	for (size_t i = 0; i < sizeof...(args); i++)
//	{
//		cout << args[i] << " ";
//	}
//	cout << endl;
//}


//参数匹配
//写无参的
//void Print()
//{
//	cout << endl;
//}

//template<class T, class ...Args>
//void Print(T&& x, Args&&... args)
//{
//	cout << x << " ";
//	Print(args...);//递归
//	// 当args...参数为0时，就调用无参，就结束递归
//
//	//运行时才判断，所以 sizeof...(args) == 0 就到不到结束条件
//	// 编译时递归不能解决
//	//if (sizeof...(args) == 0)//递归结束条件？ （错）
//	//	return;
//}

//编译时递归推到解析参数
//template<class ...Args>
//void ShowList(Args&&... args)
//{
//	Print(args...);
//}

//编译器推倒的
//void Print(double x)
//{
//	cout << x << " ";
//	Print();
//}
//
//void Print(const char* x, double z)
//{
//	cout << x << " ";
//	Print(z);
//}
//
//void Print(int x, const char* y, double z)
//{
//	cout << x << " ";
//	Print(y , z);
//}

//int main()
//{
//	ShowList();
//	ShowList(1);
//	ShowList(1, "xxxxx");
//	ShowList(1, "xxxxx", 2.2);
//	return 0;
//}

template<class T>
int PritArg(T t)
{
	cout << t << " ";
	return 0;
}

template<class ...Args>
void ShowList(Args ...args)
{
	int arr[] = { PrintArg(args)... };
	cout << endl;
}

// //编译推演生成下面的函数
//void ShowList(int x, char y, std::string z)
//{
//	int arr[] = { PrintArg(x),PrintArg(y),PrintArg(z) };
//	cout << endl;
//}

//int main()
//{
//	//ShowList(1);
//	//ShowList(1, 'A');
//	ShowList(1, 'A', std::string("sort"));
//
//	return 0;
//}

// emplace_back VS insert
int main()
{
	list<string> lt;
	//左值    
	string s1("11111111111111");
	lt.emplace_back(s1);// 构造+拷贝构造

	//右值
	lt.emplace_back(move(s1));//构造+移动构造

	//直接把构造string参数包往下传，直接用string参数构造string
	lt.emplace_back("11111111111111");//构造
	lt.emplace_back(10, 'x');//构造

	///

	list<pair<string, int>> lt1;
	//构造 pair + 拷贝/移动构造pair到list的节点中的data上
	pair<string, int> kv("小路飞", 1);
	lt1.emplace_back(kv);//构造+拷贝构造
	lt1.emplace_back(move(kv));//构造+拷贝构造

	//直接吧构造pair参数包往下传，直接用pair参数包构造pair
	lt1.emplace_back("小路飞", 1);//构造

	return 0;
}